/*
 * Description: defender exclusion handler
 */
#ifndef INSTALLATION_SCENE_ACCELERATOR_H
#define INSTALLATION_SCENE_ACCELERATOR_H
#include <atlbase.h>
#include <comutil.h>
#include <Wbemidl.h>
#include <unordered_map>
#include <mutex>
#include <regex>
#include "cJSON.h"
#include "base/perf_accelerator.h"

namespace PERF {
struct InstallPackageItem {
    std::string name = {};
    std::string fileNamePattern = {};
    std::vector<std::string> exclusiveProcesses = {};
    std::vector<std::string> exclusiveFolders = {};
    void Clear();
};

// Begin declaration of AppWhiteList

class AppWhiteList {
public:
    AppWhiteList()= default;
    ~AppWhiteList() = default;
    void Init();
    bool SearchInWhiteList(const std::string& appName, InstallPackageItem& item);
    bool IsSigned(const std::wstring& filePath);
private:
    bool ReadConfigFile_(std::string& config);
    bool ReadAppWhiteList_();
    bool ParseAppWhiteList_(const char* data);
    bool ParseApp_(cJSON* item, InstallPackageItem& parsed);
    void ParseExclusionItems(cJSON* folder, std::vector<std::string>& vItems);
    void ReplaceUserPathHolder_(std::string& path);
    std::vector<InstallPackageItem> appWhiteList_ = {};
    std::vector<std::wregex> appNameRegex_ = {};
    std::regex AppSetupPackageRegex_;
    std::mutex mutex_ = {};
    std::unordered_map<std::string, std::string> userPathHolderMap_;
    std::atomic<bool> getUserToken_{ false };
};
// End declaration of AppWhiteList

class InstallationSceneAcclerator {
public:
    void Init();
    void Quit();
    InstallationSceneAcclerator();
    ~InstallationSceneAcclerator() = default;

    bool OnBegin(std::shared_ptr<PerfInfo> perfInfo);
    bool OnEnd(std::shared_ptr<PerfInfo> perfInfo);
private:
    struct RunningProcess {
        std::string appName;
        std::set<DWORD> processId;
        std::set<std::string> exclusiveFolders;
        std::set<std::string> exclusiveProcesses;
    };
    bool Stop_(std::shared_ptr<PerfInfo> perfInfo);
    void WaitForProcessExit_(std::shared_ptr<PerfInfo> perfInfo);
    bool IsInstallScene_(std::shared_ptr<PerfInfo> perfInfo, InstallPackageItem& appConfig);
    bool AddExclusiveWorkFolder_(std::shared_ptr<PerfInfo> perfInfo, std::string& folder);
    bool RemoveExclusiveItems_(std::shared_ptr<PerfInfo> perfInfo);
    bool AddExclusiveItems_(std::shared_ptr<PerfInfo> perfInfo, const InstallPackageItem& item);
    std::unordered_map<std::string, RunningProcess> runningProcesses_;
    std::mutex mutex_;
    std::set<std::string> allowedFolder_;
    std::set<std::string> notAllowedFolder_ = {};
};
#define APPWHITELIST SingletonNew<PERF::AppWhiteList>::GetInstance()
#define INSTALLATIONSCENEACCLERATOR SingletonNew<PERF::InstallationSceneAcclerator>::GetInstance()
}
// End of namespace PERF
#endif